package pl.edu.agh.inpema.components.receivers.phpBB2Receiver.parser;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.model.Post;
import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.model.Subject;
import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.model.Topic;
import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.parser.filters.ContentTypeFilter;
import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.parser.filters.ForumLinkFilter;
import pl.edu.agh.inpema.components.receivers.phpBB2Receiver.util.Logger;

public class ForumParser {
	
	private boolean asHtml;
	private DateFormat formatter_US;
	private DateFormat formatter_PL;
	private DateFormat formatter = null;
	
	public ForumParser(String postDetailsPattern, boolean asHtml) {
		this.asHtml = asHtml;
		this.formatter_US = new SimpleDateFormat(postDetailsPattern, Locale.US);
		this.formatter_PL = new SimpleDateFormat(postDetailsPattern, new Locale("pl"));
	}
	
	public String getContentType(String page) throws ParserException {
		Parser parser = Parser.createParser(page, null);
		NodeList list = parser.extractAllNodesThatMatch(new ContentTypeFilter());
		if (list.size() != 1)
			throw new ParserException("Error while extracting META tag");
		
		Tag metaTag = (Tag) list.elementAt(0);
		
		return metaTag.getAttribute("content");
	}
	
	public List<Subject> parseMainPage(String page) throws ParserException {
		List<Subject> subjects = new LinkedList<Subject>();
		Parser parser = Parser.createParser(page, null);
		NodeList list = parser.extractAllNodesThatMatch(new ForumLinkFilter("a", ForumLinkFilter.NAME_SUBJECT_LINK));
		for (Node node : list.toNodeArray()) {
			LinkTag link = (LinkTag) node;
			String subject = link.getLinkText();
			//System.out.println(subject);
			String address = link.getLink();
			subjects.add(new Subject(subject, address));
		}
		return subjects;
	}
	
	public List<Topic> parseTopicsPage(String page) throws ParserException {
		List<Topic> topics = new LinkedList<Topic>();
		Parser parser = Parser.createParser(page, null);
		NodeList list = parser.extractAllNodesThatMatch(new ForumLinkFilter("a", ForumLinkFilter.NAME_TOPIC_LINK));
		for (Node node : list.toNodeArray()) {
			LinkTag link = (LinkTag) node;
			String subject = link.getLinkText();
			String address = link.getLink();
			topics.add(new Topic(subject, address));
		}
		return topics;
	}
	
	public List<Post> parsePostsPage(String page) throws ParserException {
		List<Post> posts = new LinkedList<Post>();
		Parser parser = Parser.createParser(page, null);

		NodeList namesNodeList = parser.extractAllNodesThatMatch(new ForumLinkFilter("span", ForumLinkFilter.NAME_POST_NAME));

		for (Node nameNode : namesNodeList.toNodeArray()) {
			
			String login = nameNode.toPlainTextString().trim().replaceAll("&nbsp;", "");

			
			Tag trParent = (Tag) nameNode.getParent();
			while (! "tr".equals(trParent.getTagName().toLowerCase())) {
				trParent = (Tag) trParent.getParent();
			}
			
			Parser postDetailsParser = Parser.createParser(trParent.toHtml(), null);
			NodeList postDeatilsNodesList = postDetailsParser.extractAllNodesThatMatch(new ForumLinkFilter("span", "postdetails"));
			postDetailsParser.reset();
			NodeList postBodyNodesList = postDetailsParser.extractAllNodesThatMatch(new ForumLinkFilter("span", "postbody"));

			Date date = null;
			for (Node postDetailsNode : postDeatilsNodesList.toNodeArray()) {
				date = this.parseDate(postDetailsNode);
				if (date != null)
					break;
			}			
			
			//System.out.println(date);
			
			if (date == null) {
				//throw new ParserException("Can't parse date.");
				Logger.logMesage("");
				Logger.logMesage("!!! Can't parse date.");
			}
			
			Node postBodyNode = postBodyNodesList.elementAt(0).getParent();
			String postBody;
			if (this.asHtml)
				postBody = postBodyNode.toHtml();
			else
				postBody = postBodyNode.toPlainTextString();
			
			Post post = new Post(login, date, postBody);
			posts.add(post);
		}
		
		return posts;
	}
	
	private Date parseDate(Node node) {
		String text = node.toPlainTextString();
		text = text.replaceAll("&nbsp;", " ");
		//System.out.println("===============");
		//System.out.println(text);
		try {
			Date date = null;
			if (this.formatter != null) {
				date = this.formatter.parse(text);
			} else {
				try {
					//System.out.println("try US");
					date = this.formatter_US.parse(text);
					this.formatter = this.formatter_US;
				} catch (ParseException e) {
					try {
						//System.out.println("try PL");
						date = this.formatter_PL.parse(text);
						this.formatter = this.formatter_PL;
					} catch (ParseException ex) {
						//System.out.println("no");
						return null;
					}
				}
			}
			return date;
		} catch (ParseException e) {
			//System.out.println("no");
			return null;
		}
	}
}
